﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

public class ConvertLatinToUnicodeExtensions
{
    public static string LatinToUnicode(this string text)
    {
        return LatinToUnicode(text, ' ');
    }

    private static string LatinToUnicode(this string text, char? replaceWithChar)
    {
        if (string.IsNullOrEmpty(text))
            return text;

        // HACK: caracter 'đ' não é montado a partir do ASCII 'd'
        // text = text.Replace('đ', 'd');

        var sb = new StringBuilder();

        // se não precisar de substituição, é mais performático
        if (!replaceWithChar.HasValue || replaceWithChar == '\0')
        {
            foreach (char c in text.Normalize(NormalizationForm.FormKD))
                if (c < 128)
                    sb.Append(c);
        }
        else
        {
            string charString;

            for (int i = 0; i < text.Length; i++)
            {
                charString = text.Substring(i, 1);
                charString = charString.Normalize(NormalizationForm.FormKD);

                // se o caracter não pode ser decomposto e for ASCII padrão (<128),
                // deixe-o como está, se for extendido (>=128), substitua-o
                if (charString.Length == 1)
                {
                    if (charString[0] < 128)
                        sb.Append(charString);
                    else
                        sb.Append(replaceWithChar);
                }
                else
                {
                    int charsCopied = 0;
                    for (int j = 0; j < charString.Length; j++)
                    {
                        char tempChar = charString[j];
                        if (tempChar < 128)
                        {
                            sb.Append(tempChar);
                            charsCopied++;
                        }
                    }
                    // se não foi possível decompor o caracter em ASCII, substitua-o
                    if (charsCopied == 0)
                        sb.Append(replaceWithChar);
                }
            }
        }

        return sb.ToString();
    }
}
